﻿using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Folding;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Media;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// 此类用以定义编辑器的折叠区。
    /// </summary>
    class CustomFoldingStrategy : AbstractFoldingStrategy
    {
        private ICSharpCode.AvalonEdit.TextEditor edit;
        /// <summary>
        /// 要应用折叠功能的编辑器。
        /// </summary>
        public ICSharpCode.AvalonEdit.TextEditor Edit { get { return this.edit; } }

        /// <summary>
        /// [构造方法]创建一个新的折叠区。
        /// </summary>
        public CustomFoldingStrategy(ICSharpCode.AvalonEdit.TextEditor edit)
        {
            this.edit = edit;

            // 自定义各折叠区的配色。
            // 1. 方块区域
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^\[[^\[\]]*\]$",
                Background = Brushes.DarkGray,
                Foreground = Brushes.White,
            });

            // 2. 自定义折叠区
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^\{[^\{\}]*\}$",
                Background = new SolidColorBrush(Color.FromRgb(255, 76, 85)),
                Foreground = Brushes.White,
            });

            // 3. Tip 块 暂时没什么功能，仅供编辑时折叠－2019年3月14日
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^\([^\(\)]*\)",
                Background = Brushes.Green,
                Foreground = Brushes.White,
            });

            // 4. 单行链接
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^[!]?\[[^\(\)]*\]\(\)$",
                Background = Brushes.SaddleBrown,
                Foreground = Brushes.White,
            });

            // 5. 六级标题
            //Ⅰ ※ xxx※
            //Ⅱ ※ 
            //Ⅲ ※ 
            //Ⅳ ※ 
            //Ⅴ ※ 
            //Ⅵ ※ 
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^Ⅰ ※ .* ※",
                Background = heading1,
                Foreground = Brushes.White,
            });
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^Ⅱ ※ .* ※",
                Background = heading2,
                Foreground = Brushes.White,
            });
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^Ⅲ ※ .* ※",
                Background = heading3,
                Foreground = Brushes.White,
            });
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^Ⅳ ※ .* ※",
                Background = heading4,
                Foreground = Brushes.White,
            });
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^Ⅴ ※ .* ※",
                Background = heading5,
                Foreground = Brushes.White,
            });
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^Ⅵ ※ .* ※",
                Background = heading6,
                Foreground = Brushes.White,
            });

            // 6. 二维文字表
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^┣.*┫$",
                Background = Brushes.Red,
                Foreground = Brushes.White,
            });

            // 6. 树型文字表
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^[!！].*$",
                Background = Brushes.Red,
                Foreground = Brushes.White,
            });

            // 7. 引用块
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^[>] .*$",
                Background = Brushes.SlateGray,
                Foreground = Brushes.White,
            });

            // 8. 用户自定义脚本块或 CSS 样式块
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^[<]((Script)|(Style)|(Math)) .*/[>]$",
                Background = htmlTag,  // 某种红色 #FFE13250
                Foreground = Brushes.WhiteSmoke,
            });

            // 9. 三个反引号开头的行
            FoldingElementGenerator.FoldingColorRules.Add(new FoldingColorRule()
            {
                RegexText = @"^`{3,}",
                Background = codeBlock,
                Foreground = Brushes.WhiteSmoke,
            });

        }

        private static SolidColorBrush heading1 = new SolidColorBrush(new Color() { A = 255, R = 255, G = 76, B = 85, });
        private static SolidColorBrush heading2 = new SolidColorBrush(new Color() { A = 255, R = 255, G = 106, B = 0, });
        private static SolidColorBrush heading3 = new SolidColorBrush(new Color() { A = 255, R = 0, G = 143, B = 0, });
        private static SolidColorBrush heading4 = new SolidColorBrush(new Color() { A = 255, R = 0, G = 142, B = 130, });
        private static SolidColorBrush heading5 = new SolidColorBrush(new Color() { A = 255, R = 7, G = 85, B = 209, });
        private static SolidColorBrush heading6 = new SolidColorBrush(new Color() { A = 255, R = 193, G = 0, B = 174, });

        private static SolidColorBrush codeBlock = new SolidColorBrush(new Color() { A = 255, R = 149, G = 151, B = 83, });
        private static SolidColorBrush htmlTag = new SolidColorBrush(new Color() { A = 255, R = 225, G = 50, B = 80, });


        /// <summary>
        /// 为特定文档创建 NewFolding 对象集。
        /// </summary>
        public override IEnumerable<NewFolding> CreateNewFoldings(TextDocument document, out int firstErrorOffset)
        {
            firstErrorOffset = -1;
            return CreateNewFoldings(document);
        }

        /// <summary>
        /// 为特定文档创建 NewFolding 对象集。
        /// </summary>
        public IEnumerable<NewFolding> CreateNewFoldings(ITextSource document)
        {
            List<NewFolding> newFoldings = new List<NewFolding>();

            var trimChars = new char[] { ' ', '　', '\t', };

            #region 使六级标题都支持折叠
            List<HeaderInfo> preHeadersInfos = new List<HeaderInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);

                string text = edit.Document.GetText(line.Offset, line.Length);

                if (text.StartsWith("#") == false && CustomMarkdownSupport.IsTaskLine(text) == false) continue;

                var headerText = GetHeaderOfTitleOrTaskListItem(text);
                var contentText = GetContentOfHeaderOrTaskListItem(text);

                var newHeaderInfo = new HeaderInfo()
                {
                    HeaderText = headerText,
                    ContentText = contentText,
                    Length = headerText.Length,
                    Offset = line.Offset,
                    EndOffset = line.EndOffset,
                };

                if (preHeadersInfos.Count <= 0)
                {
                    preHeadersInfos.Add(newHeaderInfo);
                    continue;
                }

                for (int j = preHeadersInfos.Count - 1; j >= 0; j--)
                {
                    if (newHeaderInfo.Length <= preHeadersInfos[j].Length)
                    {
                        var endOffset = newHeaderInfo.Offset - 2;//-2是\r\n的宽度

                        //如果在这个标题只有一行，不折叠
                        if (endOffset > preHeadersInfos[j].EndOffset)
                        {
                            var newFolding = new NewFolding(preHeadersInfos[j].Offset, newHeaderInfo.Offset - 2)
                            {
                                Name = BuildHeaderOrTaskListItemHeader(preHeadersInfos[j].HeaderText) +
                                    (string.IsNullOrEmpty(preHeadersInfos[j].ContentText) ?
                                    "... " :
                                    preHeadersInfos[j].ContentText) + " ※ ",
                            };
                            newFoldings.Add(newFolding);
                        }
                        preHeadersInfos.RemoveAt(j);
                    }
                }

                preHeadersInfos.Add(newHeaderInfo);
            }

            //到最后一行，看看要不要添加折叠块。
            if (preHeadersInfos.Count > 0)
            {
                var lastLine = this.edit.Document.GetLineByNumber(this.edit.Document.LineCount);
                if (lastLine != null)
                {
                    var lastLineText = this.edit.Document.GetText(lastLine);

                    if (lastLineText.StartsWith("#") == false && CustomMarkdownSupport.IsTaskLine(lastLineText) == false)
                    {

                        for (int j = preHeadersInfos.Count - 1; j >= 0; j--)
                        {
                            var endOffset = edit.Document.Lines.Last().Offset;//最后一行，没有\r\n，不用 - 2;

                            //如果在这个标题只有一行，不折叠
                            if (endOffset > preHeadersInfos[j].EndOffset)
                            {
                                newFoldings.Add(new NewFolding(preHeadersInfos[j].Offset, endOffset)
                                {
                                    Name = BuildHeaderOrTaskListItemHeader(preHeadersInfos[j].HeaderText) +
                                        (string.IsNullOrEmpty(preHeadersInfos[j].ContentText) ?
                                        "... " :
                                        preHeadersInfos[j].ContentText + " ※ "),
                                });
                            }
                            preHeadersInfos.RemoveAt(j);
                        }
                    }
                }
            }
            #endregion

            #region 添加试题所需要的折叠块
            Stack<int> startOffsets = new Stack<int>();
            string openingMark = "试题＞＞";
            string closingMark = "〓〓〓〓〓〓";

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);
                var preLine = line.PreviousLine;

                string text = edit.Document.GetText(line.Offset, line.Length).TrimStart();

                if (text.StartsWith(openingMark))
                {
                    if (preLine != null && startOffsets.Count > 0)
                    {
                        int startOffset = startOffsets.Pop();
                        // 首尾标记在同一行时不折叠。
                        if (startOffset < preLine.Offset)
                        {
                            newFoldings.Add(new NewFolding(startOffset, preLine.EndOffset)
                            {
                                Name = openingMark,
                                IsSpecial = true,
                            });
                        }
                    }

                    startOffsets.Push(line.Offset);
                }
                else if (text.StartsWith(closingMark) && startOffsets.Count > 0)
                {
                    int startOffset = startOffsets.Pop();
                    // 首尾标记在同一行时不折叠。
                    if (startOffset < line.EndOffset)
                    {
                        newFoldings.Add(new NewFolding(startOffset, line.EndOffset)
                        {
                            Name = openingMark,
                            IsSpecial = true,
                        });
                    }
                }
            }
            #endregion

            #region 使二维文字表支持折叠
            int fstTextTableLineStartOffset = -1;
            int fstTextTableLineEndOffset = -1;
            int preTextTableLineStartOffset = -1;
            int preTextTableLineEndOffset = -1;
            int currentLineEndOffset = -1;
            string tableTitle = "";

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);
                currentLineEndOffset = line.EndOffset;
                string lineText = edit.Document.GetText(line.Offset, line.Length);

                if (lineText.IndexOf('｜') >= 0 || lineText.IndexOf('|') >= 0)
                {
                    if (fstTextTableLineStartOffset < 0)
                    {
                        preTextTableLineStartOffset =
                            fstTextTableLineStartOffset = line.Offset;
                        preTextTableLineEndOffset =
                            fstTextTableLineEndOffset = line.EndOffset;

                        string[] pieces = lineText.Split(new char[] { '｜', '|' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var piece in pieces)
                        {
                            var text = piece.Trim(new char[] { ' ', '　', '\t' });
                            if (string.IsNullOrWhiteSpace(text) == false)
                            {
                                tableTitle = text;
                                break;
                            }
                        }
                    }
                    else
                    {
                        preTextTableLineStartOffset = line.Offset;
                        preTextTableLineEndOffset = line.EndOffset;
                    }
                }
                else
                {
                    if (CustomMarkdownSupport.IsCommentLine(lineText))
                    {
                        preTextTableLineStartOffset = line.Offset;
                        preTextTableLineEndOffset = line.EndOffset;
                        continue;
                    }
                    else
                    {
                        if (fstTextTableLineStartOffset >= 0 && preTextTableLineEndOffset >= 0)
                        {
                            var ttfolding = new NewFolding(fstTextTableLineStartOffset, preTextTableLineEndOffset)//不该把同级行折叠起来
                            {
                                Name = $"┣{(string.IsNullOrWhiteSpace(tableTitle) ? "文字表" : tableTitle)}┫",
                                IsSpecial = true,
                            };

                            newFoldings.Add(ttfolding);

                            //还原
                            fstTextTableLineEndOffset = -1;
                            fstTextTableLineStartOffset = -1;
                            preTextTableLineEndOffset = -1;
                            preTextTableLineStartOffset = -1;
                        }
                    }
                }
            }

            //防止最后一行也是二维文字表行。
            if (fstTextTableLineStartOffset >= 0 && preTextTableLineEndOffset >= 0)
            {
                var ttfolding = new NewFolding(fstTextTableLineStartOffset,
                    (currentLineEndOffset >= 0 ? currentLineEndOffset : preTextTableLineEndOffset))//不该把同级行折叠起来
                {
                    Name = $"二维文字表{(string.IsNullOrWhiteSpace(tableTitle) ? "" : "：")}{tableTitle}",
                    IsSpecial = true,
                };

                newFoldings.Add(ttfolding);

                //还原
                fstTextTableLineEndOffset = -1;
                fstTextTableLineStartOffset = -1;
                preTextTableLineEndOffset = -1;
                preTextTableLineStartOffset = -1;
            }
            #endregion

            #region 使引用块支持折叠
            int fstBlockQuoteLineStartOffset = -1;
            int fstBlockQuoteLineEndOffset = -1;
            int preBlockQuoteLineStartOffset = -1;
            int preBlockQuoteLineEndOffset = -1;
            int currentBlockQuoteLineEndOffset = -1;
            string blockQuoteTitle = "";

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);
                currentBlockQuoteLineEndOffset = line.EndOffset;
                string lineText = edit.Document.GetText(line.Offset, line.Length);

                if (CustomMarkdownSupport.IsBlockQuoteLine(lineText))
                {
                    if (fstBlockQuoteLineStartOffset < 0)
                    {
                        preBlockQuoteLineStartOffset =
                            fstBlockQuoteLineStartOffset = line.Offset;
                        preBlockQuoteLineEndOffset =
                            fstBlockQuoteLineEndOffset = line.EndOffset;

                        var text = lineText.Trim(new char[] { ' ', '　', '\t' });
                        Regex regexBlockQuoter = new Regex(@"^[ 　]{0,3}([>》〉]{1}[ 　]{0,}){1,}");
                        var matchBlockQuoter = regexBlockQuoter.Match(text);
                        if (matchBlockQuoter != null && matchBlockQuoter.Success)
                        {
                            text = text.Substring(matchBlockQuoter.Length);
                        }

                        if (string.IsNullOrWhiteSpace(blockQuoteTitle) && string.IsNullOrWhiteSpace(text) == false)//保留第一行作标题。
                        {
                            blockQuoteTitle = text;
                            if (blockQuoteTitle.Length > 36)
                            {
                                blockQuoteTitle = blockQuoteTitle.Substring(0, 36) + "...";
                            }
                        }
                    }
                    else
                    {
                        preBlockQuoteLineStartOffset = line.Offset;
                        preBlockQuoteLineEndOffset = line.EndOffset;
                    }
                }
                else
                {
                    if (fstBlockQuoteLineStartOffset >= 0 && preBlockQuoteLineEndOffset >= 0)
                    {
                        var bqfolding = new NewFolding(fstBlockQuoteLineStartOffset, preBlockQuoteLineEndOffset)//不该把同级行折叠起来
                        {
                            Name = $"> {(string.IsNullOrWhiteSpace(blockQuoteTitle) ? "引用块" : blockQuoteTitle)}",
                            IsSpecial = false,
                        };

                        newFoldings.Add(bqfolding);

                        //还原
                        fstBlockQuoteLineEndOffset = -1;
                        fstBlockQuoteLineStartOffset = -1;
                        preBlockQuoteLineEndOffset = -1;
                        preBlockQuoteLineStartOffset = -1;
                        blockQuoteTitle = null;
                    }
                }
            }

            //防止最后一行也是引用块行。
            if (fstBlockQuoteLineStartOffset >= 0 && preBlockQuoteLineEndOffset >= 0)
            {
                var bqfolding = new NewFolding(fstBlockQuoteLineStartOffset,
                    (currentBlockQuoteLineEndOffset >= 0 ? currentBlockQuoteLineEndOffset : preBlockQuoteLineEndOffset))//不该把同级行折叠起来
                {
                    Name = $"引用块{(string.IsNullOrWhiteSpace(blockQuoteTitle) ? "" : "：")}{blockQuoteTitle}",
                    IsSpecial = false,
                };

                newFoldings.Add(bqfolding);

                //还原
                fstBlockQuoteLineEndOffset = -1;
                fstBlockQuoteLineStartOffset = -1;
                preBlockQuoteLineEndOffset = -1;
                preBlockQuoteLineStartOffset = -1;
                blockQuoteTitle = null;
            }
            #endregion

            #region 使树型文字表支持折叠
            List<TreeListTextLine> foldTreeLines = null;
            List<List<TreeListTextLine>> listss = new List<List<TreeListTextLine>>();
            //双层列表嵌套，这是为了解决多个不连续的树型文字表

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);
                string lineText = edit.Document.GetText(line.Offset, line.Length);

                string header, tail; int level;
                if (MarkdownEditorBase.IsTreeListLine(lineText, out header, out tail, out level))
                {
                    var ti = new TreeListTextLine()
                    {
                        Line = line,
                        HeaderTextArray = header.ToCharArray(),
                        OldLevel = level,
                        NewLevel = level,
                        OldText = lineText,
                        NewText = lineText,
                        TailText = tail,
                    };

                    if (foldTreeLines == null)
                    {
                        foldTreeLines = new List<TreeListTextLine>();
                        listss.Add(foldTreeLines);
                    }

                    foldTreeLines.Add(ti);
                }
                else
                {
                    if (foldTreeLines != null) foldTreeLines = null;
                }
            }

            foreach (List<TreeListTextLine> list in listss)
            {
                if (list.Count <= 1) continue;

                for (int j = 0; j < list.Count - 1; j++)//最后一个没必要折叠
                {
                    TreeListTextLine tltl = list[j];
                    NewFolding ttfolding = null;

                    for (int k = j + 1; k < list.Count; k++)//但最后一个有必要判断是否完成折叠
                    {
                        var nexttltl = list[k];
                        if (nexttltl.NewLevel <= tltl.NewLevel)
                        {
                            //这个对象并非无意义，但不能放到下一层判断之中。
                            ttfolding = new NewFolding(tltl.Line.Offset, nexttltl.Line.Offset - 2)//不该把同级行折叠起来
                            {
                                Name = tltl.NewText,
                                IsSpecial = true,
                            };

                            if (nexttltl.Line.LineNumber > tltl.Line.LineNumber + 1)//如果只有一行，不加折叠
                            {
                                newFoldings.Add(ttfolding);
                            }
                            break;
                        }
                    }

                    if (ttfolding == null && tltl.Line.LineNumber < list[list.Count - 1].Line.LineNumber)
                    {
                        ttfolding = new NewFolding(tltl.Line.Offset, list[list.Count - 1].Line.EndOffset)
                        {
                            Name = tltl.NewText,
                            IsSpecial = true,
                        };
                        newFoldings.Add(ttfolding);
                    }
                }
            }
            #endregion

            var regAlt = new Regex(@"(?<=([aA][lL][tT][ \t]{0,}[=][ \t]{0,}['""])).*?(?=(['""]))");

            #region 数学公式 ML
            string startMath = @"^[<][Mm][Aa][Tt][Hh]([ ]{1,}.*)?[>]";
            string endMath = @"[<][/][Mm][Aa][Tt][Hh][>]";                 //短的一行就可以。

            Stack<LineInfo> mathStartLinesStackStyle = new Stack<LineInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);

                string lineText = edit.Document.GetText(line.Offset, line.Length);
                Regex regMathStart = new Regex(startMath);
                var matchMathStart = regMathStart.Match(lineText);
                var mathStartAlt = "";
                if (matchMathStart != null && matchMathStart.Success)
                {
                    var matchMathStartAlt = regAlt.Match(lineText);
                    if (matchMathStartAlt.Success)
                        mathStartAlt = matchMathStartAlt.Value.Trim(trimChars);
                    mathStartLinesStackStyle.Push(new LunarMarkdownEditor.LineInfo()
                    {
                        Line = line,
                        LineText = lineText,
                        HeaderText = lineText.Substring(matchMathStart.Length),
                        AltText = mathStartAlt,
                    });
                }
                else
                {
                    Regex regexMathEnd = new Regex(endMath);
                    var matchMathEnd = regexMathEnd.Match(lineText);

                    if (matchMathEnd != null && matchMathEnd.Success)// && preRegionLine != null)
                    {
                        if (mathStartLinesStackStyle.Count > 0)
                        {
                            var preRegionLineStyle = mathStartLinesStackStyle.Pop();
                            newFoldings.Add(new NewFolding(preRegionLineStyle.Line.Offset, line.EndOffset)
                            {
                                Name = $"<Math {preRegionLineStyle.AltText}/>",
                                IsSpecial = true,
                            });
                        }
                    }
                }
            }
            #endregion

            #region 用户自定义 JavaScript 代码块
            string startRegionScript = @"^[<][Ss][Cc][Rr][Ii][Pp][Tt]([ ]{1,}.*)?[>]";
            string endRegionScript = @"[<][/][Ss][Cc][Rr][Ii][Pp][Tt][>]";                 //短的一行就可以。

            Stack<LineInfo> regionStartLinesStackScript = new Stack<LineInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var lineScript = edit.Document.GetLineByNumber(i);

                string lineTextScript = edit.Document.GetText(lineScript.Offset, lineScript.Length);
                Regex regexStartScript = new Regex(startRegionScript);
                var matchStartScript = regexStartScript.Match(lineTextScript);
                var scriptStartAlt = "";
                if (matchStartScript != null && matchStartScript.Success)
                {
                    var matchScriptStartAlt = regAlt.Match(lineTextScript);
                    if (matchScriptStartAlt.Success)
                        scriptStartAlt = matchScriptStartAlt.Value.Trim(trimChars);
                    regionStartLinesStackScript.Push(new LunarMarkdownEditor.LineInfo()
                    {
                        Line = lineScript,
                        LineText = lineTextScript,
                        HeaderText = lineTextScript.Substring(matchStartScript.Length),
                        AltText = scriptStartAlt,
                    });
                }
                else
                {
                    Regex regexEndScript = new Regex(endRegionScript);
                    var matchEndScript = regexEndScript.Match(lineTextScript);

                    if (matchEndScript != null && matchEndScript.Success)// && preRegionLine != null)
                    {
                        if (regionStartLinesStackScript.Count > 0)
                        {
                            var preRegionLineScript = regionStartLinesStackScript.Pop();
                            newFoldings.Add(new NewFolding(preRegionLineScript.Line.Offset, lineScript.EndOffset)
                            {
                                Name = $"<Script {preRegionLineScript.AltText}/>",
                                IsSpecial = true,
                            });
                        }
                    }
                }
            }
            #endregion

            #region 用户自定义内部样式表区域
            string startRegionStyle = @"^[<][Ss][Tt][Yy][Ll][Ee]([ ]{1,}.*)?[>]";
            string endRegionStyle = @"[<][/][Ss][Tt][Yy][Ll][Ee][>]";                 //短的一行就可以。

            Stack<LineInfo> regionStartLinesStackStyle = new Stack<LineInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var lineStyle = edit.Document.GetLineByNumber(i);

                string lineTextStyle = edit.Document.GetText(lineStyle.Offset, lineStyle.Length);
                Regex regexStartStyle = new Regex(startRegionStyle);
                var matchStartStyle = regexStartStyle.Match(lineTextStyle);
                var styleStartAlt = "";
                if (matchStartStyle != null && matchStartStyle.Success)
                {
                    var matchStyleStartAlt = regAlt.Match(lineTextStyle);
                    if (matchStyleStartAlt.Success)
                        styleStartAlt = matchStyleStartAlt.Value.Trim(trimChars);
                    regionStartLinesStackStyle.Push(new LunarMarkdownEditor.LineInfo()
                    {
                        Line = lineStyle,
                        LineText = lineTextStyle,
                        HeaderText = lineTextStyle.Substring(matchStartStyle.Length),
                        AltText = styleStartAlt,
                    });
                }
                else
                {
                    Regex regexEndStyle = new Regex(endRegionStyle);
                    var matchEndStyle = regexEndStyle.Match(lineTextStyle);

                    if (matchEndStyle != null && matchEndStyle.Success)// && preRegionLine != null)
                    {
                        if (regionStartLinesStackStyle.Count > 0)
                        {
                            var preRegionLineStyle = regionStartLinesStackStyle.Pop();
                            newFoldings.Add(new NewFolding(preRegionLineStyle.Line.Offset, lineStyle.EndOffset)
                            {
                                Name = $"<Style {preRegionLineStyle.AltText}/>",
                                IsSpecial = true,
                            });
                        }
                    }
                }
            }
            #endregion

            #region 添加方块文本
            string startRegionS = @"^\[[\[\]]*?";
            string endRegionS = @"^\][\[\]]*?";

            Stack<LineInfo> regionStartLinesStackS = new Stack<LineInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var lineS = edit.Document.GetLineByNumber(i);

                string lineTextS = edit.Document.GetText(lineS.Offset, lineS.Length);
                Regex regexStartS = new Regex(startRegionS);
                var matchStartS = regexStartS.Match(lineTextS);

                if (matchStartS != null && matchStartS.Success)
                {
                    regionStartLinesStackS.Push(new LunarMarkdownEditor.LineInfo()
                    {
                        Line = lineS,
                        LineText = lineTextS,
                        HeaderText = lineTextS.Substring(matchStartS.Length),
                    });
                }
                else
                {
                    Regex regexEndS = new Regex(endRegionS);
                    var matchEndS = regexEndS.Match(lineTextS);

                    if (matchEndS != null && matchEndS.Success)// && preRegionLine != null)
                    {
                        if (regionStartLinesStackS.Count > 0)
                        {
                            var preRegionLineS = regionStartLinesStackS.Pop();
                            newFoldings.Add(new NewFolding(preRegionLineS.Line.Offset, lineS.EndOffset)
                            {
                                Name = (preRegionLineS.HeaderText == null ? $"[{lineTextS.Substring(matchEndS.Length).Trim(trimChars)}]" : $"[{preRegionLineS.HeaderText.Trim(trimChars)}]"),
                                IsSpecial = true,
                            });
                        }
                    }
                }
            }
            #endregion

            #region 添加 Tip 块支持
            string startRegionT = @"^[;；][(（][ 　\t]*?";
            string endRegionT = @"[;；][)）][ 　\t]*?";

            Stack<LineInfo> regionStartLinesStackT = new Stack<LineInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var lineT = edit.Document.GetLineByNumber(i);

                string lineTextT = edit.Document.GetText(lineT.Offset, lineT.Length);
                Regex regexStartT = new Regex(startRegionT);
                var matchStartT = regexStartT.Match(lineTextT);

                if (matchStartT != null && matchStartT.Success)
                {
                    regionStartLinesStackT.Push(new LunarMarkdownEditor.LineInfo()
                    {
                        Line = lineT,
                        LineText = lineTextT,
                        HeaderText = lineTextT.Substring(matchStartT.Length),
                    });
                }
                else
                {
                    Regex regexEndT = new Regex(endRegionT);
                    var matchEndT = regexEndT.Match(lineTextT);

                    if (matchEndT != null && matchEndT.Success)// && preRegionLine != null)
                    {
                        if (regionStartLinesStackT.Count > 0)
                        {
                            var preRegionLineT = regionStartLinesStackT.Pop();
                            newFoldings.Add(new NewFolding(preRegionLineT.Line.Offset, lineT.EndOffset)
                            {
                                Name = (preRegionLineT.HeaderText == null ? $"({lineTextT.Substring(matchEndT.Length).Trim(trimChars)})" : $"({preRegionLineT.HeaderText.Trim(trimChars)})"),
                                IsSpecial = true,
                            });
                        }
                    }
                }
            }

            #endregion

            #region 添加自定义折叠块
            string startRegion = @"^[ 　]{0,3}([rｒRＲ][eｅEＥ][gｇGＧ][iｉIＩ][oｏOＯ][nｎNＮ][ 　\t]*)?([!?！？ＩＷＥＱIWEQｉｗｅｑiweq][ 　\t]*)?\{[ 　\t]*";
            string endRegion = @"^[ 　]{0,3}\}[ 　\t]*([rｒRＲ][eｅEＥ][gｇGＧ][iｉIＩ][oｏOＯ][nｎNＮ][ 　\t]*)?";

            Stack<LineInfo> regionStartLinesStack = new Stack<LineInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);

                string lineText = edit.Document.GetText(line.Offset, line.Length);
                Regex regexStart = new Regex(startRegion);
                var matchStart = regexStart.Match(lineText);

                if (matchStart != null && matchStart.Success)
                {
                    regionStartLinesStack.Push(new LunarMarkdownEditor.LineInfo()
                    {
                        Line = line,
                        LineText = lineText,
                        HeaderText = lineText.Substring(matchStart.Length),
                    });
                }
                else
                {
                    Regex regexEnd = new Regex(endRegion);
                    var matchEnd = regexEnd.Match(lineText);

                    if (matchEnd != null && matchEnd.Success)// && preRegionLine != null)
                    {
                        if (regionStartLinesStack.Count > 0)
                        {
                            var preRegionLine = regionStartLinesStack.Pop();
                            newFoldings.Add(new NewFolding(preRegionLine.Line.Offset, line.EndOffset)
                            {
                                Name = (preRegionLine.HeaderText == null ? $"{{{lineText.Substring(matchEnd.Length)}}}" : $"{{{preRegionLine.HeaderText}}}"),
                                IsSpecial = true,
                            });
                        }
                    }
                }
            }
            #endregion

            #region 单行图像链接折叠或文件链接
            Regex regImageOrFileHeader = new Regex(@"(?<=(!?\[)).*(?=\])");
            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);

                string lineText = edit.Document.GetText(line.Offset, line.Length);

                if (CustomMarkdownSupport.IsImageLinkLine(lineText))
                {
                    var matchImageHeader = regImageOrFileHeader.Match(lineText);
                    newFoldings.Add(new NewFolding(line.Offset, line.EndOffset)
                    {
                        Name = (matchImageHeader.Success && string.IsNullOrWhiteSpace(matchImageHeader.Value) == false) ? $"![{matchImageHeader.Value}]()" : "![图像链接]()",
                        IsSpecial = true,
                    });
                }
                else if (CustomMarkdownSupport.IsFileLinkLine(lineText))
                {
                    var matchFileHeader = regImageOrFileHeader.Match(lineText);
                    newFoldings.Add(new NewFolding(line.Offset, line.EndOffset)
                    {
                        Name = (matchFileHeader.Success && string.IsNullOrWhiteSpace(matchFileHeader.Value) == false) ? $"[{matchFileHeader.Value}]()" : "[文件链接]()",
                        IsSpecial = true,
                    });
                }
            }
            #endregion

            #region 三个反引号行
            string codeBlock = @"^`{3,}";
            Stack<LineInfo> regionCodeBlock = new Stack<LineInfo>();

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var lineCodeBlock = edit.Document.GetLineByNumber(i);

                string lineTextCodeBlock = edit.Document.GetText(lineCodeBlock.Offset, lineCodeBlock.Length);
                Regex regexCodeBlock = new Regex(codeBlock);
                var matchCodeBlock = regexCodeBlock.Match(lineTextCodeBlock);

                if (matchCodeBlock != null && matchCodeBlock.Success)
                {
                    if (regionCodeBlock.Count > 0)
                    {
                        var preCodeBlock = regionCodeBlock.Pop();
                        newFoldings.Add(new NewFolding(preCodeBlock.Line.Offset, lineCodeBlock.EndOffset)
                        {
                            Name = (preCodeBlock.HeaderText == null ? $"[{lineTextCodeBlock.Substring(matchCodeBlock.Length).Trim(trimChars)}]" : $"[{preCodeBlock.HeaderText.Trim(trimChars)}]"),
                            IsSpecial = true,
                        });
                    }
                    else
                    {
                        regionCodeBlock.Push(new LunarMarkdownEditor.LineInfo()
                        {
                            Line = lineCodeBlock,
                            LineText = lineTextCodeBlock,
                            HeaderText = lineTextCodeBlock.Substring(matchCodeBlock.Length),
                        });
                    }
                }
            }
            #endregion

            newFoldings.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset));
            return newFoldings;
        }

        /// <summary>
        /// 生成标题或任务列表被折叠时显示的文本。
        /// </summary>
        /// <param name="sourceText">如果是 Header，只应传入“###”部分，不应包括后面的内容。</param>
        private string BuildHeaderOrTaskListItemHeader(string sourceText)
        {
            if (string.IsNullOrWhiteSpace(sourceText)) return "";

            if (sourceText.StartsWith("[-]") || sourceText.StartsWith("[－]")) return "[-] ";
            if (sourceText.StartsWith("[+]")) return "[+] ";
            if (sourceText.StartsWith("[%]")) return "[%] ";
            if (sourceText.StartsWith("[#]")) return "[#] ";

            var level = sourceText.Length;
            switch (level)
            {
                case 1: return "Ⅰ ※ ";
                case 2: return "Ⅱ ※ ";
                case 3: return "Ⅲ ※ ";
                case 4: return "Ⅳ ※ ";
                case 5: return "Ⅴ ※ ";
                case 6: return "Ⅵ ※ ";
                default: return "";
            }
        }

        /// <summary>
        /// 取标题或任务列表的文字部分（去除标志文本、空白字符等）。
        /// </summary>
        /// <param name="src">源文本</param>
        public string GetContentOfHeaderOrTaskListItem(string src)
        {
            if (string.IsNullOrEmpty(src)) return "";

            if (CustomMarkdownSupport.IsTaskLine(src)) return CustomMarkdownSupport.GetContentOfTaskListItem(src);

            if (src.StartsWith("#") == false) return "";

            if (src.StartsWith("######")) return src.Substring(6);
            if (src.StartsWith("#####")) return src.Substring(5);
            if (src.StartsWith("####")) return src.Substring(4);
            if (src.StartsWith("###")) return src.Substring(3);
            if (src.StartsWith("##")) return src.Substring(2);
            if (src.StartsWith("#")) return src.Substring(1);

            return "";
        }

        /// <summary>
        /// 取标题或任务列表的标志文本（不包含其它表示具体意思的文本）。
        /// </summary>
        /// <param name="src">源文本</param>
        public string GetHeaderOfTitleOrTaskListItem(string src)
        {
            if (string.IsNullOrEmpty(src)) return "";
            if (CustomMarkdownSupport.IsTaskLine(src))
            {
                return CustomMarkdownSupport.GetHeaderOfTaskListItem(src);
            }
            if (src.StartsWith("#") == false) return "";

            if (src.StartsWith("######")) return "######";
            if (src.StartsWith("#####")) return "#####";
            if (src.StartsWith("####")) return "####";
            if (src.StartsWith("###")) return "###";
            if (src.StartsWith("##")) return "##";
            if (src.StartsWith("#")) return "#";

            return "";
        }
    }

    /// <summary>
    /// 提供六级标题的折叠功能时，此类用于记录某个标题的相关位置信息。
    /// </summary>
    public class HeaderInfo
    {
        private string headerText = "...";
        public string HeaderText
        {
            get { return this.headerText; }
            set { this.headerText = value; }
        }

        private string contentText = "#";
        public string ContentText
        {
            get { return contentText; }
            set { this.contentText = value; }
        }

        private int length = 1;
        public int Length
        {
            get { return this.length; }
            set { this.length = value; }
        }

        private int offset = -1;
        public int Offset
        {
            get { return this.offset; }
            set { this.offset = value; }
        }

        private int endOffset = -1;
        public int EndOffset
        {
            get { return this.endOffset; }
            set { this.endOffset = value; }
        }

    }

    public class LineInfo
    {
        public DocumentLine Line { get; set; }
        public string LineText { get; set; } = "";
        public string HeaderText { get; set; } = "";
        public string AltText { get; set; } = "";
    }
}
